package com.xiaoy.core.bpm.engine.activiti.activiti5;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.activiti.engine.history.HistoricActivityInstance;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.impl.RepositoryServiceImpl;
import org.activiti.engine.impl.bpmn.diagram.ProcessDiagramGenerator;
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.activiti.engine.impl.pvm.PvmTransition;
import org.activiti.engine.impl.pvm.process.ActivityImpl;
import org.activiti.engine.impl.pvm.process.TransitionImpl;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.DeploymentBuilder;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.springframework.stereotype.Service;

import com.google.common.collect.Lists;
import com.xiaoy.core.bpm.engine.entity.InstanceProcessVO;
import com.xiaoy.core.bpm.engine.entity.ProcessDefineVO;
import com.xiaoy.core.bpm.engine.entity.ProcessInstantiate;
import com.xiaoy.core.bpm.engine.entity.ProcessNodeVO;
import com.xiaoy.core.bpm.engine.entity.ProcessTask;
import com.xiaoy.core.bpm.engine.exception.BPMEngineException;

@Service("workFlowActiviti5Impl")
public class WorkFlowActiviti5Impl extends EngineActiviti5{

	@Override
	public void delete(String id) {
		
	}

	@Override
	public List<ProcessInstantiate> getProcessInstancesByDefineId(String defineId) {
		
		List<HistoricProcessInstance> hpis = historyService.createHistoricProcessInstanceQuery().processDefinitionId(defineId).list();
		
		List<ProcessInstantiate> pis = Lists.newArrayList();
		for (HistoricProcessInstance hpi :hpis) {
			pis.add(historicProcessInstanceToProcessInstantiate(hpi));
		}
		return pis;
	}

	@Override
	public List<ProcessDefineVO> getAllProcessDefinitions() throws BPMEngineException{
	
		List<ProcessDefinition> processDefinitions = repositoryService.createProcessDefinitionQuery().list();
		
//		List<Deployment> deployments = repositoryService.createDeploymentQuery().list();
		
//		for (Deployment d:deployments) {
//			System.out.println(d.getId()+"-"+d.getName());
//		}
		
		List<ProcessDefineVO> infos = new ArrayList<ProcessDefineVO>();
		System.out.println("ProcessDefinitions:");
		for (ProcessDefinition define : processDefinitions) {
		
			infos.add(processDefinitionToProcessDefineVO(define));
		}
		
		return infos;
	}

	@Override
	public ProcessInstantiate createProcessInstanceById(InstanceProcessVO vo) throws BPMEngineException {
		
		
		ProcessInstance processInstance=null;
		
		Object o = vo.getParam(APPLY_USER);
		if (o!=null) {
			identityService.setAuthenticatedUserId(o.toString());
		}
		
		if (null!=vo.getId()&&!"".equals(vo.getId())) {
			processInstance = this.runtimeService.startProcessInstanceById(vo.getId(),vo.getParams());
		}else {
			processInstance = this.runtimeService.startProcessInstanceByKey(vo.getKey(),vo.getParams());
		}
		
		ProcessInstantiate instance = new ProcessInstantiate();
		instance.setProcessInstanceId(processInstance.getProcessInstanceId());
		
//		processInstance.getBusinessKey();

		return instance;
	}

	public void defineProcess () {
		
		try{
			DeploymentBuilder builder = repositoryService.createDeployment();
			builder = builder.addClasspathResource("qingjia.bpmn");
			Deployment deployment = builder.deploy();
			System.out.println("deployment:"+deployment.getId()+"="+deployment.getName());
		}catch(Exception e){
			e.printStackTrace();
		}
		
		
		
//		 repositoryService.createDeployment()  
//         .addClasspathResource("Interview.bpmn")  
//         .deploy();  
		
		
	}
	
	@Override
	public ProcessDefineVO defineProcess(Object...objs) throws BPMEngineException{
		
		DeploymentBuilder builder = repositoryService.createDeployment();
		builder.addInputStream(objs[0].toString(), (InputStream) objs[1]);
//		builder = builder.addClasspathResource(objs[0].toString());
//		builder.addString("applyUser", "cty");
		Deployment deployment = builder.deploy();
		
		System.out.println("DefineProcess:"
				+"id:"+deployment.getId()
				+" - getName:"+deployment.getName()
				+" - "+deployment.getDeploymentTime()
				+" - getCategory:"+deployment.getCategory()
			);
		
	    ProcessDefinition p = repositoryService.createProcessDefinitionQuery().deploymentId(deployment.getId()).singleResult();
	    
		ProcessDefineVO define = processDefinitionToProcessDefineVO(p);
		
//		define.setKey(p.getKey());
//		define.setDeploymentId(deployment.getId());
		define.setCreateDate(deployment.getDeploymentTime());
		define.setVersion(deployment.getCategory());;
//		define.setName(deployment.getName());
		
		return define;
	}
	@Override
	public InputStream getProcessImageByProcessDefineId (String processDefineId) {
//		repositoryService.createProcessDefinitionQuery().list();
		
		
//		repositoryService.getResourceAsStream(processDefinition.getDeploymentId(), processDefinition.getDiagramResourceName());
		
		
		
		return repositoryService.getProcessDiagram(processDefineId);
//		runtimeService.createProcessInstanceQuery().l
		
	}
	
	
	@Override
	public ProcessDefineVO getProcessDefinitionByDeployMentId(String deployMentId) throws BPMEngineException {
	
		ProcessDefinition pd = repositoryService.createProcessDefinitionQuery().deploymentId(deployMentId).singleResult();
		
		return processDefinitionToProcessDefineVO(pd);
	}

	@Override
	public List<ProcessTask> getTaskByUsername(String user) {
		
		// 使用taskService根据用户ID获取候选任务
		List<Task> tasks = taskService.createTaskQuery()
		.taskAssignee(user)
		.orderByTaskCreateTime()
		.desc()
		.list();
		
		List<ProcessTask> ptasks = Lists.newArrayList();
		
		for (Task task : tasks) {
			
			ptasks.add(taskToProcessTaskVO(task));
		}
		return ptasks;
	}
	
	//	查询流程中所有节点
	@Override
	public List<ProcessNodeVO> getProcessNodesByDefineId (String defineId) {

		
		List<ProcessNodeVO> nodeVOs = Lists.newArrayList();
		
		ProcessDefinitionEntity processDefinition = (ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService)
		        .getDeployedProcessDefinition(defineId);
		
		List<ActivityImpl> activitiList = processDefinition.getActivities();
		
		for (ActivityImpl activity : activitiList) {
			
		    Map<String, Object> properties = activity.getProperties();

	    	ProcessNodeVO vo = new ProcessNodeVO();
	    	vo.setId(activity.getId());
	    	vo.setName(properties.get("name").toString());
	    	vo.setType(properties.get("type").toString());
	    	
	    	nodeVOs.add(vo);
		}
		
		
		//-----------------------------------------------
		
		
//		List<ProcessDefinition> pds = repositoryService.createProcessDefinitionQuery().list();
		
//		for (ProcessDefinition definition :pds) {
//			ProcessDefinitionEntity processDefinition = (ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService)
//			        .getDeployedProcessDefinition(definition.getId());
//			List<ActivityImpl> activitiList = processDefinition.getActivities();
//			for (ActivityImpl activity : activitiList) {
//			    Map<String, Object> properties = activity.getProperties();
//		    	
//		    	ProcessNodeVO vo = new ProcessNodeVO();
//		    	vo.setId(activity.getId());
//		    	vo.setName(properties.get("name").toString());
//		    	vo.setType(properties.get("type").toString());
//		    	
//		    	nodeVOs.add(vo);
//			   
//			    String type = properties.get("type").toString();
//			    if (type.equals("exclusiveGateway")) {
//			    	
//			        List<PvmTransition> outgoingTransitions = activity.getOutgoingTransitions();
//			        for (PvmTransition outgoingTransition : outgoingTransitions) {
//			            TransitionImpl ti = (TransitionImpl) outgoingTransition;
//			            System.out.println(ti.getProperties());
//			        }
//			    } else {
//			        System.out.println(properties);
//			    }
//			    System.out.println("-------------------------------------------------------");
//			}
//			
//		}
		
		return nodeVOs;
	}
	
	
	//
	@Override
	public List<ProcessTask> getCurrentProcessTaskByInstanceId (String instanceId) {
		
//		List<Task> tasks = taskService.createTaskQuery().processDefinitionId(defineId).list();
//		
//		List<ProcessTask> ptasks = Lists.newArrayList();
//		for (Task task : tasks) {
//			
//			ptasks.add(taskToProcessTask(task));
//		}
					  
		List<Task> tasks = taskService.createTaskQuery().processInstanceId(instanceId).list();
		List<ProcessTask> ptasks = Lists.newArrayList();
		for (Task task : tasks) {
			ptasks.add(taskToProcessTaskVO(task));
		}
		return ptasks;
	}
	
	 /**
     * 获得user完成的流程的任务节点
     * @param user
     * @return
     */
	public List<HistoricActivityInstance> getHistoryTasksByUsername (String user) {
		
		List<HistoricActivityInstance> list = historyService
				.createHistoricActivityInstanceQuery().taskAssignee(user)
				.orderByHistoricActivityInstanceEndTime().desc().finished()
				.list();
		
		return list;
	}
	
    /**
     * 获得user已完成的流程实例
     * @param user
     * @return
     */
	public List<HistoricProcessInstance> getHistoryProcessInstanceByUsername (String user) {
		
		List<HistoricProcessInstance> list = historyService
				.createHistoricProcessInstanceQuery().orderByProcessInstanceStartTime().desc().finished().list();
		
		return list;
	}
	
	
	
//	处理中的流程实例查询
//	RuntimeService runtimeService = processEngine.getRuntimeService();
//	List<ProcessInstance> processInstanceList = runtimeService.createProcessInstanceQuery().list();
	
//	处理完成的流程实例查询
//	HistoricProcessInstanceQuery historicProcessInstanceQuery = processEngine.getHistoryService()
//	.createHistoricProcessInstanceQuery();
//	List<HistoricProcessInstance> historicProcessInstanceList = historicProcessInstanceQuery.finished().orderByProcessInstanceStartTime().asc().list();
	
	
	
	
//	流程处理记录查询
//	l? 仅得到流程中的UserTask节点
//	HistoricTaskInstanceQuery historicTaskInstanceQuery = processEngine.getHistoryService()
//	?????????????????? .createHistoricTaskInstanceQuery();
//	List<HistoricTaskInstance> historicTaskInstanceList = historicTaskInstanceQuery.processInstanceId(processInstanceId)
//	?????????????????? .orderByHistoricActivityInstanceStartTime().asc().list();

	
	@Override
	public InputStream getProcessImageByInstanceId(String instanceId) throws BPMEngineException{
		
		
		ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(instanceId).singleResult();
		String definitionId = processInstance.getProcessDefinitionId();
		ProcessDefinitionEntity  pd = (ProcessDefinitionEntity) repositoryService.getProcessDefinition(definitionId);
		return ProcessDiagramGenerator.generateDiagram(pd, "png", runtimeService.getActiveActivityIds(instanceId));
		
	}
	
	@Override
	public List <ProcessDefineVO> myApply(String username)throws BPMEngineException{
//		runtimeService.createProcessInstanceQuery().new
//		List<HistoricTaskInstance> tasks = historyService.createHistoricTaskInstanceQuery().taskAssignee(username).list();
		List<HistoricProcessInstance> hpis = historyService.createHistoricProcessInstanceQuery().startedBy(username).orderByProcessInstanceStartTime().list();
		List <ProcessDefineVO> pds = Lists.newArrayList();
		for (HistoricProcessInstance hpi : hpis) {
			String defineId = hpi.getProcessDefinitionId();
			ProcessDefinition p = repositoryService.getProcessDefinition(defineId);
			ProcessDefineVO vo = processDefinitionToProcessDefineVO(p);
			vo.setInstanceId(hpi.getId());
			pds.add(vo);
		}
		return pds;
//		repositoryService.createProcessDefinitionQuery().
		
//		List<HistoricActivityInstance> hais = historyService
//				.createHistoricActivityInstanceQuery()
//				.activityId("startevent1").taskAssignee(username)
//				.orderByHistoricActivityInstanceStartTime().list();
		
		
		
//		for (HistoricTaskInstance task:tasks) {
//			System.out.println(task.getOwner());
//		}
	}
	//-----------------------------------------------
	
	public ProcessTask taskToProcessTaskVO (Task task) {
		
		ProcessTask e = new ProcessTask();
		
		String assignee = task.getAssignee();
		String name = task.getName();
		String taskId = task.getId();
		String owner = task.getOwner();
		String executionId = task.getExecutionId();
		String instanceId = task.getProcessInstanceId();
		
		System.out.println("taskId:"+taskId+" - name:"+name+" - executionId:"+executionId+" - instanceId:"+instanceId+" - assignee:"+assignee+" - owner:"+owner);
		
		e.setAssignee(assignee);
		e.setName(name);
		e.setTaskId(taskId);
		e.setOwner(owner);
		e.setExecutionId(executionId);
		
		return e;
	}
	
	public ProcessDefineVO processDefinitionToProcessDefineVO (ProcessDefinition define) {
		
		ProcessDefineVO vo = new ProcessDefineVO();
		String deploymentId = define.getDeploymentId();
		String name = define.getName();
		String id = define.getId();
		String key = define.getKey();
		
		System.out.println("deploymentId:"+deploymentId+" - name:"+name+" - id:"+id+" - key:"+key+" - ResourceName:"+define.getResourceName());
		
		vo.setDeploymentId(deploymentId);
		vo.setName(name);
		vo.setId(id);
		vo.setKey(key);
		
		return vo;
	}
	
	public ProcessInstantiate historicProcessInstanceToProcessInstantiate (HistoricProcessInstance hpi) {
		
		ProcessInstantiate pi = new ProcessInstantiate();
		
		pi.setProcessDefineId(hpi.getProcessDefinitionId());
		pi.setProcessInstanceId(hpi.getId());
		
		return pi;
	}
	
	
	
	
	
}
